home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / HENSA / MATHS / PLPLOT / PLPLOT.ZIP / src / plstring.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-30  |  16.9 KB  |  624 lines

  1. /* $Id: plstring.c,v 1.8 1994/06/30 18:22:18 mjl Exp $
  2.  * $Log: plstring.c,v $
  3.  * Revision 1.8  1994/06/30  18:22:18  mjl
  4.  * All core source files: made another pass to eliminate warnings when using
  5.  * gcc -Wall.  Lots of cleaning up: got rid of includes of math.h or string.h
  6.  * (now included by plplot.h), and other minor changes.  Now each file has
  7.  * global access to the plstream pointer via extern; many accessor functions
  8.  * eliminated as a result.
  9.  *
  10.  * Revision 1.7  1994/03/23  08:34:00  mjl
  11.  * All external API source files: replaced call to plexit() on simple
  12.  * (recoverable) errors with simply printing the error message (via
  13.  * plabort()) and returning.  Should help avoid loss of computer time in some
  14.  * critical circumstances (during a long batch run, for example).
  15. */
  16.  
  17. /*    plstring.c
  18.  
  19.     Text & string handling routines.
  20. */
  21.  
  22. #include "plplotP.h"
  23. #include <ctype.h>
  24.  
  25. #define PLMAXSTR    300
  26. #define STLEN        250
  27.  
  28. static char font[] = "nris";
  29. static char greek[] = "ABGDEZYHIKLMNCOPRSTUFXQWabgdezyhiklmncoprstufxqw";
  30. static short symbol[PLMAXSTR];
  31. static SCHAR xygrid[STLEN];
  32.  
  33. extern SCHAR *fntbffr;
  34. extern short int *fntindx;
  35. extern short int indxleng;
  36. extern short int *fntlkup;
  37. extern short int numberfonts, numberchars;
  38.  
  39. /* Static function prototypes */
  40.  
  41. static void  pldeco    (short **, PLINT *, const char *);
  42. static void  plchar    (SCHAR *, PLFLT *, PLINT, PLINT, PLINT,
  43.              PLINT, PLINT, PLFLT, PLFLT, PLFLT, PLFLT, PLFLT,
  44.              PLFLT *, PLFLT *, PLFLT *);
  45.  
  46. /*----------------------------------------------------------------------*\
  47.  * void pllab()
  48.  *
  49.  * Simple routine for labelling graphs.
  50. \*----------------------------------------------------------------------*/
  51.  
  52. void
  53. c_pllab(const char *xlabel, const char *ylabel, const char *tlabel)
  54. {
  55.     if (plsc->level < 2) {
  56.     plabort("pllab: Please set up viewport first");
  57.     return;
  58.     }
  59.  
  60.     plmtex("t", (PLFLT) 2.0, (PLFLT) 0.5, (PLFLT) 0.5, tlabel);
  61.     plmtex("b", (PLFLT) 3.2, (PLFLT) 0.5, (PLFLT) 0.5, xlabel);
  62.     plmtex("l", (PLFLT) 5.0, (PLFLT) 0.5, (PLFLT) 0.5, ylabel);
  63. }
  64.  
  65. /*----------------------------------------------------------------------*\
  66.  * void plmtex()
  67.  *
  68.  * Prints out "text" at specified position relative to viewport
  69.  * (may be inside or outside)
  70.  *
  71.  * side    String which is one of the following:
  72.  *    B or b  :  Bottom of viewport
  73.  *    T or t  :  Top of viewport
  74.  *    L or l  :  Left of viewport
  75.  *    R or r  :  Right of viewport
  76.  *    LV or lv : Left of viewport, vertical text
  77.  *    RV or rv : Right of viewport, vertical text
  78.  * disp    Displacement from specified edge of viewport, measured
  79.  *    outwards from the viewport in units of the current
  80.  *    character height. The centerlines of the characters are
  81.  *    aligned with the specified position.
  82.  * pos    Position of the reference point of the string relative
  83.  *    to the viewport edge, ranging from 0.0 (left-hand edge)
  84.  *    to 1.0 (right-hand edge)
  85.  * just    Justification of string relative to reference point
  86.  *    just = 0.0 => left hand edge of string is at reference
  87.  *    just = 1.0 => right hand edge of string is at reference
  88.  *    just = 0.5 => center of string is at reference
  89. \*----------------------------------------------------------------------*/
  90.  
  91. void
  92. c_plmtex(const char *side, PLFLT disp, PLFLT pos, PLFLT just,
  93.      const char *text)
  94. {
  95.     PLINT clpxmi, clpxma, clpymi, clpyma;
  96.     PLINT sppxmi, sppxma, sppymi, sppyma;
  97.     PLINT vert, refx, refy;
  98.     PLFLT shift, xform[4];
  99.     PLFLT vpdxmi, vpdxma, vpdymi, vpdyma;
  100.     PLFLT chrdef, chrht;
  101.     PLFLT mpxscl, mpxoff, mpyscl, mpyoff;
  102.  
  103.     if (plsc->level < 2) {
  104.     plabort("plmtex: Please set up viewport first");
  105.     return;
  106.     }
  107.  
  108.     /* Open clip limits to subpage limits */
  109.  
  110.     plP_gclp(&clpxmi, &clpxma, &clpymi, &clpyma);
  111.     plP_gspp(&sppxmi, &sppxma, &sppymi, &sppyma);
  112.     plP_sclp(sppxmi, sppxma, sppymi, sppyma);
  113.  
  114.     plP_gvpd(&vpdxmi, &vpdxma, &vpdymi, &vpdyma);
  115.     plP_gmp(&mpxscl, &mpxoff, &mpyscl, &mpyoff);
  116.     plgchr(&chrdef, &chrht);
  117.  
  118.     shift = 0.0;
  119.     if (just != 0.0)
  120.     shift = just * plstrl(text);
  121.  
  122.     if (plP_stsearch(side, 'b')) {
  123.     vert = 0;
  124.     refx = plP_dcpcx((PLFLT) (vpdxmi + (vpdxma - vpdxmi) * pos)) -
  125.         shift * mpxscl;
  126.     refy = plP_mmpcy((PLFLT) (plP_dcmmy(vpdymi) - disp * chrht));
  127.     }
  128.     else if (plP_stsearch(side, 't')) {
  129.     vert = 0;
  130.     refx = plP_dcpcx((PLFLT) (vpdxmi + (vpdxma - vpdxmi) * pos)) -
  131.         shift * mpxscl;
  132.     refy = plP_mmpcy((PLFLT) (plP_dcmmy(vpdyma) + disp * chrht));
  133.     }
  134.     else if (plP_stindex(side, "LV") != -1 || plP_stindex(side, "lv") != -1) {
  135.     vert = 0;
  136.     refy = plP_dcpcy((PLFLT) (vpdymi + (vpdyma - vpdymi) * pos));
  137.     refx = plP_mmpcx((PLFLT) (plP_dcmmx(vpdxmi) - disp * chrht - shift));
  138.     }
  139.     else if (plP_stindex(side, "RV") != -1 || plP_stindex(side, "rv") != -1) {
  140.     vert = 0;
  141.     refy = plP_dcpcy((PLFLT) (vpdymi + (vpdyma - vpdymi) * pos));
  142.     refx = plP_mmpcx((PLFLT) (plP_dcmmx(vpdxma) + disp * chrht - shift));
  143.     }
  144.     else if (plP_stsearch(side, 'l')) {
  145.     vert = 1;
  146.     refy = plP_dcpcy((PLFLT) (vpdymi + (vpdyma - vpdymi) * pos)) -
  147.         shift * mpyscl;
  148.     refx = plP_mmpcx((PLFLT) (plP_dcmmx(vpdxmi) - disp * chrht));
  149.     }
  150.     else if (plP_stsearch(side, 'r')) {
  151.     vert = 1;
  152.     refy = plP_dcpcy((PLFLT) (vpdymi + (vpdyma - vpdymi) * pos)) -
  153.         shift * mpyscl;
  154.     refx = plP_mmpcx((PLFLT) (plP_dcmmx(vpdxma) + disp * chrht));
  155.     }
  156.     else {
  157.     plP_sclp(clpxmi, clpxma, clpymi, clpyma);
  158.     return;
  159.     }
  160.  
  161.     if (vert != 0) {
  162.     xform[0] = 0.0;
  163.     xform[1] = -1.0;
  164.     xform[2] = 1.0;
  165.     xform[3] = 0.0;
  166.     }
  167.     else {
  168.     xform[0] = 1.0;
  169.     xform[1] = 0.0;
  170.     xform[2] = 0.0;
  171.     xform[3] = 1.0;
  172.     }
  173.     plstr(0, xform, refx, refy, text);
  174.     plP_sclp(clpxmi, clpxma, clpymi, clpyma);
  175. }
  176.  
  177. /*----------------------------------------------------------------------*\
  178.  * void plptex()
  179.  *
  180.  * Prints out "text" at world cooordinate (x,y). The text may be
  181.  * at any angle "angle" relative to the horizontal. The parameter
  182.  * "just" adjusts the horizontal justification of the string:
  183.  *    just = 0.0 => left hand edge of string is at (x,y)
  184.  *    just = 1.0 => right hand edge of string is at (x,y)
  185.  *    just = 0.5 => center of string is at (x,y) etc.
  186. \*----------------------------------------------------------------------*/
  187.  
  188. void
  189. c_plptex(PLFLT x, PLFLT y, PLFLT dx, PLFLT dy, PLFLT just, const char *text)
  190. {
  191.     PLINT refx, refy;
  192.     PLFLT shift, cc, ss;
  193.     PLFLT xform[4], diag;
  194.     PLFLT xscl, xoff, yscl, yoff;
  195.  
  196.     if (plsc->level < 3) {
  197.     plabort("plptex: Please set up window first");
  198.     return;
  199.     }
  200.  
  201.     plP_gwm(&xscl, &xoff, &yscl, &yoff);
  202.  
  203.     if (dx == 0.0 && dy == 0.0) {
  204.     dx = 1.0;
  205.     dy = 0.0;
  206.     }
  207.     cc = xscl * dx;
  208.     ss = yscl * dy;
  209.     diag = sqrt(cc * cc + ss * ss);
  210.     cc = cc / diag;
  211.     ss = ss / diag;
  212.  
  213.     plP_gmp(&xscl, &xoff, &yscl, &yoff);
  214.     shift = 0.0;
  215.  
  216.     xform[0] = cc;
  217.     xform[1] = -ss;
  218.     xform[2] = ss;
  219.     xform[3] = cc;
  220.  
  221.     if (just != 0.0)
  222.     shift = plstrl(text) * just;
  223.     refx = plP_wcpcx(x) - shift * cc * xscl;
  224.     refy = plP_wcpcy(y) - shift * ss * yscl;
  225.     plstr(0, xform, refx, refy, text);
  226. }
  227.  
  228. /*----------------------------------------------------------------------*\
  229.  * void plstr()
  230.  *
  231.  * Prints out a "string" at reference position with physical coordinates
  232.  * (refx,refy). The coordinates of the vectors defining the string are
  233.  * passed through the linear mapping defined by the 2 x 2 matrix xform()
  234.  * before being plotted.  The reference position is at the left-hand edge of
  235.  * the string. If base = 1, it is aligned with the baseline of the string.
  236.  * If base = 0, it is aligned with the center of the character box.
  237.  *
  238.  * Note, all calculations are done in terms of millimetres. These are scaled
  239.  * as necessary before plotting the string on the page.
  240. \*----------------------------------------------------------------------*/
  241.  
  242. void
  243. plstr(PLINT base, PLFLT *xform, PLINT refx, PLINT refy, const char *string)
  244. {
  245.     short int *symbol;
  246.     SCHAR *xygrid;
  247.     PLINT ch, i, length, level, style, oline, uline;
  248.     PLFLT width, xorg, yorg, def, ht, dscale, scale;
  249.     PLFLT xscl, xoff, yscl, yoff;
  250.  
  251.     width = 0.0;
  252.     oline = 0;
  253.     uline = 0;
  254.  
  255.     plgchr(&def, &ht);
  256.     dscale = 0.05 * ht;
  257.     scale = dscale;
  258.     plP_gmp(&xscl, &xoff, &yscl, &yoff);
  259.  
  260. /* Line style must be continuous */
  261.  
  262.     style = plsc->nms;
  263.     plsc->nms = 0;
  264.  
  265.     pldeco(&symbol, &length, string);
  266.     xorg = 0.0;
  267.     yorg = 0.0;
  268.     level = 0;
  269.  
  270.     for (i = 0; i < length; i++) {
  271.     ch = symbol[i];
  272.     if (ch == -1) {
  273.         level = level + 1;
  274.         yorg = yorg + 16.0 * scale;
  275.         scale = dscale * pow(0.75, (double) ABS(level));
  276.     }
  277.     else if (ch == -2) {
  278.         level = level - 1;
  279.         scale = dscale * pow(0.75, (double) ABS(level));
  280.         yorg = yorg - 16.0 * scale;
  281.     }
  282.     else if (ch == -3)
  283.         xorg = xorg - width * scale;
  284.     else if (ch == -4)
  285.         oline = !oline;
  286.     else if (ch == -5)
  287.         uline = !uline;
  288.     else {
  289.         if (plcvec(ch, &xygrid))
  290.         plchar(xygrid, xform, base, oline, uline, refx, refy, scale,
  291.                xscl, xoff, yscl, yoff, &xorg, &yorg, &width);
  292.     }
  293.     }
  294.     plsc->nms = style;
  295. }
  296.  
  297. /*----------------------------------------------------------------------*\
  298.  * plchar()
  299.  *
  300.  * Plots out a given stroke font character.
  301. \*----------------------------------------------------------------------*/
  302.  
  303. static void
  304. plchar(SCHAR *xygrid, PLFLT *xform, PLINT base, PLINT oline, PLINT uline, 
  305.        PLINT refx, PLINT refy, PLFLT scale,
  306.        PLFLT xscl, PLFLT xoff, PLFLT yscl, PLFLT yoff,
  307.        PLFLT *p_xorg, PLFLT *p_yorg, PLFLT *p_width)
  308. {
  309.     PLINT xbase, ybase, ydisp, lx, ly, cx, cy;
  310.     PLINT k, penup;
  311.     PLFLT x, y;
  312.  
  313.     xbase = xygrid[2];
  314.     *p_width = xygrid[3] - xbase;
  315.     if (base == 0) {
  316.     ybase = 0;
  317.     ydisp = xygrid[0];
  318.     }
  319.     else {
  320.     ybase = xygrid[0];
  321.     ydisp = 0;
  322.     }
  323.     k = 4;
  324.     penup = 1;
  325.     for (;;) {
  326.     cx = xygrid[k++];
  327.     cy = xygrid[k++];
  328.     if (cx == 64 && cy == 64)
  329.         break;
  330.     if (cx == 64 && cy == 0)
  331.         penup = 1;
  332.     else {
  333.         x = *p_xorg + (cx - xbase) * scale;
  334.         y = *p_yorg + (cy - ybase) * scale;
  335.         lx = refx + ROUND(xscl * (xform[0] * x + xform[1] * y));
  336.         ly = refy + ROUND(yscl * (xform[2] * x + xform[3] * y));
  337.         if (penup != 0) {
  338.         plP_movphy(lx, ly);
  339.         penup = 0;
  340.         }
  341.         else
  342.         plP_draphy(lx, ly);
  343.     }
  344.     }
  345.  
  346.     if (oline) {
  347.     x = *p_xorg;
  348.     y = *p_yorg + (30 + ydisp) * scale;
  349.     lx = refx + ROUND(xscl * (xform[0] * x + xform[1] * y));
  350.     ly = refy + ROUND(yscl * (xform[2] * x + xform[3] * y));
  351.     plP_movphy(lx, ly);
  352.     x = *p_xorg + *p_width * scale;
  353.     lx = refx + ROUND(xscl * (xform[0] * x + xform[1] * y));
  354.     ly = refy + ROUND(yscl * (xform[2] * x + xform[3] * y));
  355.     plP_draphy(lx, ly);
  356.     }
  357.     if (uline) {
  358.     x = *p_xorg;
  359.     y = *p_yorg + (-5 + ydisp) * scale;
  360.     lx = refx + ROUND(xscl * (xform[0] * x + xform[1] * y));
  361.     ly = refy + ROUND(yscl * (xform[2] * x + xform[3] * y));
  362.     plP_movphy(lx, ly);
  363.     x = *p_xorg + *p_width * scale;
  364.     lx = refx + ROUND(xscl * (xform[0] * x + xform[1] * y));
  365.     ly = refy + ROUND(yscl * (xform[2] * x + xform[3] * y));
  366.     plP_draphy(lx, ly);
  367.     }
  368.     *p_xorg = *p_xorg + *p_width * scale;
  369. }
  370.  
  371. /*----------------------------------------------------------------------*\
  372.  * PLFLT plstrl()
  373.  *
  374.  * Computes the length of a string in mm, including escape sequences.
  375. \*----------------------------------------------------------------------*/
  376.  
  377. PLFLT
  378. plstrl(const char *string)
  379. {
  380.     short int *symbol;
  381.     SCHAR *xygrid;
  382.     PLINT ch, i, length, level;
  383.     PLFLT width, xorg, dscale, scale, def, ht;
  384.     PLFLT xscl, xoff, yscl, yoff;
  385.  
  386.     width = 0.0;
  387.     plgchr(&def, &ht);
  388.     dscale = 0.05 * ht;
  389.     scale = dscale;
  390.     plP_gmp(&xscl, &xoff, &yscl, &yoff);
  391.  
  392.     pldeco(&symbol, &length, string);
  393.     xorg = 0.0;
  394.     level = 0;
  395.  
  396.     for (i = 0; i < length; i++) {
  397.     ch = symbol[i];
  398.     if (ch == -1) {
  399.         level = level + 1;
  400.         scale = dscale * pow(0.75, (double) ABS(level));
  401.     }
  402.     else if (ch == -2) {
  403.         level = level - 1;
  404.         scale = dscale * pow(0.75, (double) ABS(level));
  405.     }
  406.     else if (ch == -3)
  407.         xorg = xorg - width * scale;
  408.     else if (ch == -4 || ch == -5);
  409.     else {
  410.         if (plcvec(ch, &xygrid)) {
  411.         width = xygrid[3] - xygrid[2];
  412.         xorg = xorg + width * scale;
  413.         }
  414.     }
  415.     }
  416.     return ((PLFLT) xorg);
  417. }
  418.  
  419. /*----------------------------------------------------------------------*\
  420.  * PLINT plcvec()
  421.  *
  422.  * Gets the character digitisation of Hershey table entry "char".
  423.  * Returns 1 if there is a valid entry.
  424. \*----------------------------------------------------------------------*/
  425.  
  426. PLINT
  427. plcvec(PLINT ch, SCHAR ** xygr)
  428. {
  429.     PLINT k, ib;
  430.     SCHAR x, y;
  431.  
  432.     ch--;
  433.     if (ch < 0 || ch >= indxleng)
  434.     return ((PLINT) 0);
  435.     ib = fntindx[ch] - 2;
  436.     if (ib == -2)
  437.     return ((PLINT) 0);
  438.  
  439.     k = 0;
  440.     do {
  441.     ib++;
  442.     x = fntbffr[2 * ib];
  443.     y = fntbffr[2 * ib + 1];
  444.     xygrid[k++] = x;
  445.     xygrid[k++] = y;
  446.     } while ((x != 64 || y != 64) && k <= (STLEN - 2));
  447.  
  448.     *xygr = xygrid;
  449.     return ((PLINT) 1);
  450. }
  451.  
  452. /*----------------------------------------------------------------------*\
  453.  * void pldeco()
  454.  *
  455.  * Decode a character string, and return an array of float integer symbol
  456.  * numbers. This routine is responsible for interpreting all escape sequences.
  457.  * At present the following escape sequences are defined (the letter following
  458.  * the <esc> may be either upper or lower case):
  459.  *
  460.  * <esc>u    : up one level (returns -1)
  461.  * <esc>d    : down one level (returns -2)
  462.  * <esc>b    : backspace (returns -3)
  463.  * <esc>+    : toggles overline mode (returns -4)
  464.  * <esc>-    : toggles underline mode (returns -5)
  465.  * <esc><esc>    : <esc>
  466.  * <esc>gx    : greek letter corresponding to roman letter x
  467.  * <esc>fn    : switch to Normal font
  468.  * <esc>fr    : switch to Roman font
  469.  * <esc>fi    : switch to Italic font
  470.  * <esc>fs    : switch to Script font
  471.  * <esc>(nnn)    : Hershey symbol number nnn (any number of digits)
  472.  *
  473.  * The escape character defaults to '#', but can be changed to any of
  474.  * [!#$%&*@^~] via a call to plsesc.
  475. \*----------------------------------------------------------------------*/
  476.  
  477. static void
  478. pldeco(short int **sym, PLINT *length, const char *text)
  479. {
  480.     PLINT ch, icol, ifont, ig, j, lentxt;
  481.     char test, esc;
  482.  
  483. /* Initialize parameters. */
  484.  
  485.     lentxt = strlen(text);
  486.     *length = 0;
  487.     *sym = symbol;
  488.     plP_gatt(&ifont, &icol);
  489.     plgesc(&esc);
  490.     if (ifont > numberfonts)
  491.     ifont = 1;
  492.  
  493. /* Get next character; treat non-printing characters as spaces. */
  494.  
  495.     j = 0;
  496.     while (j < lentxt) {
  497.     if (*length >= PLMAXSTR)
  498.         return;
  499.     test = text[j++];
  500.     ch = test;
  501.     if (ch < 0 || ch > 175)
  502.         ch = 32;
  503.  
  504. /* Test for escape sequence (#) */
  505.  
  506.     if (ch == esc && (lentxt - j) >= 1) {
  507.         test = text[j++];
  508.         if (test == esc)
  509.         symbol[(*length)++] = *(fntlkup + (ifont - 1) * numberchars + ch);
  510.  
  511.         else if (test == 'u' || test == 'U')
  512.         symbol[(*length)++] = -1;
  513.  
  514.         else if (test == 'd' || test == 'D')
  515.         symbol[(*length)++] = -2;
  516.  
  517.         else if (test == 'b' || test == 'B')
  518.         symbol[(*length)++] = -3;
  519.  
  520.         else if (test == '+')
  521.         symbol[(*length)++] = -4;
  522.  
  523.         else if (test == '-')
  524.         symbol[(*length)++] = -5;
  525.  
  526.         else if (test == '(') {
  527.         symbol[*length] = 0;
  528.         while ('0' <= text[j] && text[j] <= '9') {
  529.             symbol[*length] = symbol[*length] * 10 + text[j] - '0';
  530.             j++;
  531.         }
  532.         (*length)++;
  533.         if (text[j] == ')')
  534.             j++;
  535.         }
  536.         else if (test == 'f' || test == 'F') {
  537.         test = text[j++];
  538.         ifont = plP_strpos(font, isupper(test) ? tolower(test) : test) + 1;
  539.         if (ifont == 0 || ifont > numberfonts)
  540.             ifont = 1;
  541.         }
  542.         else if (test == 'g' || test == 'G') {
  543.         test = text[j++];
  544.         ig = plP_strpos(greek, test) + 1;
  545.         symbol[(*length)++] = *(fntlkup + (ifont - 1) * numberchars +
  546.                     127 + ig);
  547.         }
  548.         else {
  549.         ;
  550.         }
  551.     }
  552.     else {
  553.  
  554. /* Decode character. */
  555. /* >>PC<< removed increment from following expression to fix compiler bug */
  556.  
  557.         symbol[(*length)] = *(fntlkup + (ifont - 1) * numberchars + ch);
  558.         (*length)++;
  559.     }
  560.     }
  561. }
  562.  
  563. /*----------------------------------------------------------------------*\
  564.  * PLINT plP_strpos()
  565.  *
  566.  * Searches string str for first occurence of character chr.  If found
  567.  * the position of the character in the string is returned (the first
  568.  * character has position 0).  If the character is not found a -1 is
  569.  * returned.
  570. \*----------------------------------------------------------------------*/
  571.  
  572. PLINT
  573. plP_strpos(char *str, int chr)
  574. {
  575.     char *temp;
  576.  
  577.     if ((temp = strchr(str, chr)))
  578.     return ((PLINT) (temp - str));
  579.     else
  580.     return ((PLINT) -1);
  581. }
  582.  
  583. /*----------------------------------------------------------------------*\
  584.  * PLINT plP_stindex()
  585.  *
  586.  * Similar to strpos, but searches for occurence of string str2.
  587. \*----------------------------------------------------------------------*/
  588.  
  589. PLINT
  590. plP_stindex(const char *str1, const char *str2)
  591. {
  592.     PLINT base;
  593.     PLINT str1ind;
  594.     PLINT str2ind;
  595.  
  596.     for (base = 0; *(str1 + base) != '\0'; base++) {
  597.     for (str1ind = base, str2ind = 0; *(str2 + str2ind) != '\0' &&
  598.          *(str2 + str2ind) == *(str1 + str1ind); str1ind++, str2ind++);
  599.  
  600.     /* no body */
  601.  
  602.     if (*(str2 + str2ind) == '\0')
  603.         return ((PLINT) base);
  604.     }
  605.     return ((PLINT) -1);    /* search failed */
  606. }
  607.  
  608. /*----------------------------------------------------------------------*\
  609.  * PLINT plP_stsearch()
  610.  *
  611.  * Searches string str for character chr (case insensitive).
  612. \*----------------------------------------------------------------------*/
  613.  
  614. PLINT
  615. plP_stsearch(const char *str, int chr)
  616. {
  617.     if (strchr(str, chr))
  618.     return ((PLINT) 1);
  619.     else if (strchr(str, toupper(chr)))
  620.     return ((PLINT) 1);
  621.     else
  622.     return ((PLINT) 0);
  623. }
  624.